const httpStatus = require('http-status');
const { SearchHistory } = require('../models');
const ApiError = require('../utils/ApiError');
const logger = require('../utils/logger');
const mongoose = require('mongoose');

/**
 * 创建搜索历史记录
 * @param {Object} historyData - 搜索历史数据
 * @returns {Promise<Object>} 创建的搜索历史对象
 */
const createSearchHistory = async (historyData) => {
  try {
    logger.info(`开始创建搜索历史记录: ${JSON.stringify(historyData)}`);
    
    // 确保userId存在
    if (!historyData.userId) {
      logger.error('创建搜索历史失败: 缺少用户ID');
      throw new ApiError(httpStatus.BAD_REQUEST, '创建搜索历史记录需要用户ID');
    }
    
    // 详细记录userId信息
    logger.info(`处理用户ID: ${historyData.userId}, 类型: ${typeof historyData.userId}`);
    
    // 确保userId是有效的ObjectId
    let userObjectId;
    try {
      // 如果已经是ObjectId实例，直接使用
      if (historyData.userId instanceof mongoose.Types.ObjectId) {
        userObjectId = historyData.userId;
        logger.info('用户ID已经是ObjectId实例');
      } else if (typeof historyData.userId === 'object' && historyData.userId._id) {
        // 如果是包含_id的对象
        userObjectId = new mongoose.Types.ObjectId(historyData.userId._id);
        logger.info('从用户对象中提取_id并转换为ObjectId');
      } else {
        // 尝试转换字符串为ObjectId
        try {
          userObjectId = new mongoose.Types.ObjectId(historyData.userId);
          logger.info('成功将用户ID字符串转换为ObjectId');
        } catch (err) {
          // 如果转换失败，检查是否为有效字符串表示
          if (typeof historyData.userId === 'string' && historyData.userId.length === 24) {
            userObjectId = new mongoose.Types.ObjectId(historyData.userId);
            logger.info('成功将24位用户ID字符串转换为ObjectId');
          } else {
            throw new Error(`无效的ObjectId格式: ${historyData.userId}`);
          }
        }
      }
    } catch (err) {
      logger.error(`用户ID格式无效: ${JSON.stringify(historyData.userId)}, 错误: ${err.message}`);
      logger.error(`用户ID类型: ${typeof historyData.userId}`);
      // 返回友好错误而不抛出异常，使搜索功能不受影响
      return { error: true, message: '用户ID格式无效，无法保存搜索历史' };
    }
    
    // 检查搜索关键词
    if (!historyData.keyword || historyData.keyword.trim() === '') {
      logger.error('创建搜索历史失败: 搜索关键词为空');
      return { error: true, message: '搜索关键词不能为空' };
    }
    
    // 创建搜索历史记录
    const searchHistory = await SearchHistory.create({
      userId: userObjectId,
      keyword: historyData.keyword.trim(),
      type: historyData.type || 'food',
    });
    
    logger.info(`搜索历史记录创建成功, ID: ${searchHistory._id}`);
    return searchHistory;
  } catch (error) {
    // MongoDB错误处理
    if (error.name === 'ValidationError') {
      logger.error(`数据验证错误: ${JSON.stringify(error.errors)}`);
      return { error: true, message: '搜索历史数据验证失败' };
    }
    
    if (error.code === 11000) {
      logger.error(`唯一性约束冲突: ${JSON.stringify(error)}`);
      // 对于重复搜索可以选择忽略或更新时间戳
      return { error: true, message: '搜索历史记录已存在' };
    }
    
    // 如果已经是ApiError则直接抛出
    if (error instanceof ApiError) {
      return { error: true, message: error.message };
    }
    
    logger.error(`创建搜索历史记录失败: ${error.message}`);
    logger.error(`错误堆栈: ${error.stack}`);
    return { error: true, message: '保存搜索历史失败' };
  }
};

/**
 * 获取用户的搜索历史
 * @param {string} userId - 用户ID
 * @param {Object} options - 查询选项
 * @returns {Promise<Array>} 搜索历史列表
 */
const getUserSearchHistory = async (userId, options = {}) => {
  try {
    const { limit = 20, type } = options;
    
    if (!userId) {
      logger.error('获取搜索历史失败: 缺少用户ID');
      throw new ApiError(httpStatus.BAD_REQUEST, '获取搜索历史需要用户ID');
    }
    
    // 确保userId是有效的ObjectId
    let userObjectId;
    try {
      // 如果已经是ObjectId实例，直接使用
      if (userId instanceof mongoose.Types.ObjectId) {
        userObjectId = userId;
      } else {
        // 如果是字符串，转换为ObjectId
        userObjectId = new mongoose.Types.ObjectId(userId);
      }
    } catch (err) {
      logger.error(`用户ID格式无效: ${userId}, 错误: ${err.message}`);
      throw new ApiError(httpStatus.BAD_REQUEST, '用户ID格式无效');
    }
    
    const filter = { userId: userObjectId };
    if (type) {
      filter.type = type;
    }
    
    logger.info(`查询用户搜索历史, 过滤条件: ${JSON.stringify(filter)}`);
    
    const searchHistory = await SearchHistory.find(filter)
      .sort({ createdAt: -1 })
      .limit(limit)
      .lean();
    
    logger.info(`查询到 ${searchHistory.length} 条搜索历史记录`);
    return searchHistory;
  } catch (error) {
    if (error instanceof ApiError) {
      throw error;
    }
    
    logger.error(`获取用户搜索历史失败: ${error.message}`);
    logger.error(`错误堆栈: ${error.stack}`);
    throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, '获取搜索历史失败');
  }
};

/**
 * 清除用户的搜索历史
 * @param {string} userId - 用户ID
 * @param {string} type - 搜索类型，可选
 * @returns {Promise<Object>} 删除结果
 */
const clearUserSearchHistory = async (userId, type) => {
  try {
    if (!userId) {
      logger.error('清除搜索历史失败: 缺少用户ID');
      throw new ApiError(httpStatus.BAD_REQUEST, '清除搜索历史需要用户ID');
    }
    
    // 确保userId是有效的ObjectId
    let userObjectId;
    try {
      // 如果已经是ObjectId实例，直接使用
      if (userId instanceof mongoose.Types.ObjectId) {
        userObjectId = userId;
      } else {
        // 如果是字符串，转换为ObjectId
        userObjectId = new mongoose.Types.ObjectId(userId);
      }
    } catch (err) {
      logger.error(`用户ID格式无效: ${userId}, 错误: ${err.message}`);
      throw new ApiError(httpStatus.BAD_REQUEST, '用户ID格式无效');
    }
    
    const filter = { userId: userObjectId };
    if (type) {
      filter.type = type;
    }
    
    logger.info(`准备清除用户搜索历史, 过滤条件: ${JSON.stringify(filter)}`);
    
    const result = await SearchHistory.deleteMany(filter);
    logger.info(`已清除用户(${userId})的${type ? type + '类型' : '全部'}搜索历史, 共${result.deletedCount}条记录`);
    
    return {
      deletedCount: result.deletedCount
    };
  } catch (error) {
    if (error instanceof ApiError) {
      throw error;
    }
    
    logger.error(`清除用户搜索历史失败: ${error.message}`);
    logger.error(`错误堆栈: ${error.stack}`);
    throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, '清除搜索历史失败');
  }
};

module.exports = {
  createSearchHistory,
  getUserSearchHistory,
  clearUserSearchHistory,
}; 